//
// Created by Administrator on 2021/5/23.
//

#include "../fmacros.h"
#include "client.h"

#include "../socket.h"
#include "../define.h"
#include "../protocol.h"

#include <stdio.h>
#include <string.h>
#include <unistd.h>

int client_do_package(package_t *req_package, package_t **resp_package) {
    int ret = ANET_OK;
    char body[64];
    printf("receive msg, type:%d data:%s\n", req_package->head.type, req_package->data);
    switch (req_package->head.type) {
        case PROTOCOL_REGISTER:
            snprintf(body, sizeof(body), "%s", "type is ack info!!!");
            *resp_package = alloc_packet((uint32_t) strlen(body) + 1);
            (*resp_package)->head.type = PROTOCOL_ACK;
            if (*resp_package) {
                memcpy((*resp_package)->data, body, strlen(body) + 1);
            } else {
                printf("alloc package error, OOM");
            }
            break;
        case PROTOCOL_ACK:
            snprintf(body, sizeof(body), "%s", "type is cancel info!!!");
            *resp_package = alloc_packet((uint32_t) strlen(body) + 1);
            (*resp_package)->head.type = PROTOCOL_CANCEL;
            if (*resp_package) {
                memcpy((*resp_package)->data, body, strlen(body) + 1);
            } else {
                printf("alloc package error, OOM");
            }
            break;
        case PROTOCOL_CANCEL:
            ret = ANET_ERR;
            break;
        default:
            printf("Unknown package, pcode: %d\n", req_package->head.type);
            ret = ANET_ERR;
            break;
    }
    return ret;
}

void init_client(client_t *client, char *host, int port) {
    char err[ANET_ERR_LEN];
    client->fd = anetTcpConnect(err, host, port);
    if (client->fd == ANET_ERR) {
        printf("connect error: %s\n", err);
        return;
    }

    char conn_info[64];
    anetFormatPeer(client->fd, conn_info, sizeof(conn_info));
    printf("connect to: %s success\n", conn_info);
}

void free_client(client_t *client) {
    printf("client disconnect, close it. client fd:%d\n", client->fd);
    if (client) {
        if (client->fd > 0) {
            close(client->fd);
        }
    }
}

static void writeEventHandler(client_t *client, uint32_t type, char *send_info) {
    char send_buff[1024];
    snprintf(send_buff, sizeof(send_buff), "%s", send_info);

    package_t *package = alloc_packet((uint32_t) strlen(send_buff) + 1);
    package->head.type = type;
    memcpy(package->data, send_buff, strlen(send_buff) + 1);

    int package_len = sizeof(package_head_t) + package->head.length;
    printf("fd:%d, send package size: %d\n", client->fd, package_len);
    int send_len = anetWrite(client->fd, (char *) package, package_len);
    if (send_len != package_len) {
        printf("send error, exit.");
    }

    free_package(package);
}

static void writeEventHandler2(client_t *client, package_t *send_package) {
    int package_len = sizeof(package_head_t) + send_package->head.length;
    printf("fd:%d, send package size: %d\n", client->fd, package_len);
    int send_len = anetWrite(client->fd, (char *) send_package, package_len);
    if (send_len != package_len) {
        printf("send error, exit.");
    }

    free_package(send_package);
}

static void readEventHandler(client_t *client) {
    char buff[1024];
    if (anetRead(client->fd, buff, sizeof(package_head_t)) < 0) {
        printf("read error, exit.");
        return;
    }
    package_t *resp_package = (package_t *) buff;
//    printf("resp_package info, type:%d, length: %d\n",
//           resp_package->head.type, resp_package->head.length);
    if (anetRead(client->fd, buff + sizeof(package_head_t), resp_package->head.length) < 0) {
        printf("read error, exit.");
        return;
    }

    package_t *send_package = NULL;
    int ret = client_do_package(resp_package, &send_package);
    if (ret != ANET_OK) {
        free_client(client);
        return;
    }
    if (send_package) {
        writeEventHandler2(client, send_package);
    }
}

int main() {
    client_t client;
    init_client(&client, "127.0.0.1", DEFAULT_LISTEN_PORT);
    if (client.fd == ANET_ERR) {
        return -1;
    }

    writeEventHandler(&client, PROTOCOL_REGISTER, "type is register info!!!");
    readEventHandler(&client);

    free_client(&client);
    return 0;
}
